#include "EvalBleedThroughAdd.hpp"


#include <girlTools/girlToolsDiskBackup.hpp>
#include <girlTools/girlToolsRegionInfos.hpp>
#include <ise/iseQuantificationThresholderOtsu.hpp>
#include <ise/iseGrayScaleHistogram.hpp>
#include <ise/iseHashHistogram.hpp>


#include <vector>



EvalBleedThroughAdd::EvalBleedThroughAdd()
    :_versoBinarisation(NULL),
    _versoRegions(NULL),
    _versoToger(NULL)
{}

EvalBleedThroughAdd::EvalBleedThroughAdd(const girl::tools::Image &pverso)
    : _versoBinarisation(NULL),
    _versoRegions(NULL),
    _versoToger(NULL)
{}



void EvalBleedThroughAdd::init()
{
    BleedThroughParameters *params = dynamic_cast<BleedThroughParameters * >(_params);

    girl::tools::Image verso = getVerso();
    girl::tools::Image out (verso);
    for(int i=0; i< verso.width(); i++)
    {
        for(int j=0; j< verso.height(); j++)
        {

            int min = 255;
            for(int k =-1; k < 1; k++){
                for(int l =-1; l < 1; l++)
                {
                    int x = i+k;
                    int y = j+l;
                    if(x < 0) x =0;
                    if(y < 0) y =0;
                    if(x > verso.width() -1 ) x = verso.width() -1;
                    if(y > verso.height() -1 ) y = verso.height() -1;

                    int pixel =verso.getPixel(x,y).a();
                    if(pixel < min)
                        min = pixel;
                }
            }
            girl::tools::Pixel o(min,min,min);


            out.setPixel(i,j,o);
        }
    }

    ///Determination du seuil de binarisation global;
    _seuil = _thresholder.getVersoTreshold(verso);

    _versoBinarisation = new GlobalThresholdBinarisation(out,_seuil);
    _versoRegions = _versoBinarisation->underThdRegions();

    _versoToger = _versoBinarisation->toger();
}


EvalBleedThroughAdd::~EvalBleedThroughAdd()
{delete _versoBinarisation;}


float EvalBleedThroughAdd::evaluate(const girl::tools::Image &image)
{
    BleedThroughParameters *params = dynamic_cast<BleedThroughParameters * >(_params);
    //determination du seuil

    int seuil = _thresholder.getRectoThreshold(image,getVerso(),_seuil);
    std::cout << "NBAddEval" << std::endl;
    std::cout << seuil  << std::endl;

    //Binarisation
    GlobalThresholdBinarisation rectoBinarisation(image,seuil);
    girl::regionDeque * rectoRegions = rectoBinarisation.underThdRegions();
    girl::toger * rectoToger = rectoBinarisation.toger();

    girl::regionDeque::iterator versoIt = _versoRegions->begin();
    girl::regionDeque::iterator versoItEnd = _versoRegions->end();


    // on ne veut pas des composante trop petite et sup à 20% de l'air moyen
    int nb_add =0;
    int areas = girl::tools::computeArea(*_versoToger,*versoIt);
    int nbAreas = 1;

    for(; versoIt != versoItEnd; ++versoIt)
    {
        bool in = false;
        girl::region r_verso = *versoIt;

        //Bounding Box
        girl::point p1;
        girl::point p2;
        girl::tools::computeBoundingBox(*_versoToger,r_verso,p1,p2);

        girl::regionDeque::iterator rectoIt = rectoRegions->begin();
        girl::regionDeque::iterator rectoItEnd = rectoRegions->end();
        for(; rectoIt != rectoItEnd; ++rectoIt)
        {
            girl::region r_recto = *rectoIt;
            //On recupere le domain de la region du recto
            std::vector<girl::point> points;
            rectoToger->regionDomain(r_recto,points);

            //Mise à jour de l'aire moyenne
            int currentArea = girl::tools::computeArea(*rectoToger,*rectoIt);
            areas+= currentArea;
            nbAreas++;


            if(currentArea > 20 * (areas/nbAreas) /100){
                for(int i = 0; i<points.size() && !in;i++)
                {
                    in = (points[i].x() >= p1.x() && points[i].x() <= p2.x()
                          && points[i].y() >= p1.y() && points[i].y() <= p2.y());
                }
            }
        }
        if(!in)
            nb_add++;
    }

    float mesure = float(nb_add) / float(_versoRegions->size());

    return mesure;

}
